/*
 * CommonUtil.java
 */

package xq.util;

import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

/**
 *
 * @author ThorntonRP
 */
public final class CommonUtil {

	/**
	 * Returns the minimum value from the given array as determined by the
	 * supplied comparator.
	 * @param <T> 
	 * @param a
	 * @param c 
	 * @return
	 */
	public static <T> T min(T[] a, Comparator<? super T> c) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			T min = a[0];
			for (int i = 1; i < a.length; i++) {
				if (c.compare(a[i], min) < 0) {
					min = a[i];
				}
			}
			return min;
		}
	}

	/**
	 * Returns the minimum value from the given array.
	 * @param <T> 
	 * @param a
	 * @return
	 */
	public static <T extends Comparable<? super T>> T min(T[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			T min = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i].compareTo(min) < 0) {
					min = a[i];
				}
			}
			return min;
		}
	}

	/**
	 * Returns the minimum value from the given array.
	 * @param a
	 * @return
	 */
	public static byte min(byte[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			byte min = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] < min) {
					min = a[i];
				}
			}
			return min;
		}
	}

	/**
	 * Returns the minimum value from the given array.
	 * @param a
	 * @return
	 */
	public static char min(char[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			char min = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] < min) {
					min = a[i];
				}
			}
			return min;
		}
	}

	/**
	 * Returns the minimum value from the given array.
	 * @param a
	 * @return
	 */
	public static double min(double[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			double min = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] < min) {
					min = a[i];
				}
			}
			return min;
		}
	}

	/**
	 * Returns the minimum value from the given array.
	 * @param a
	 * @return
	 */
	public static float min(float[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			float min = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] < min) {
					min = a[i];
				}
			}
			return min;
		}
	}

	/**
	 * Returns the minimum value from the given array.
	 * @param a
	 * @return
	 */
	public static int min(int[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			int min = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] < min) {
					min = a[i];
				}
			}
			return min;
		}
	}

	/**
	 * Returns the minimum value from the given array.
	 * @param a
	 * @return
	 */
	public static long min(long[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			long min = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] < min) {
					min = a[i];
				}
			}
			return min;
		}
	}

	/**
	 * Returns the minimum value from the given array.
	 * @param a
	 * @return
	 */
	public static short min(short[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			short min = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] < min) {
					min = a[i];
				}
			}
			return min;
		}
	}


	/**
	 * Returns the maximum value from the given array as determined by the
	 * supplied comparator.
	 * @param <T> 
	 * @param a
	 * @param c 
	 * @return
	 */
	public static <T> T max(T[] a, Comparator<? super T> c) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			T max = a[0];
			for (int i = 1; i < a.length; i++) {
				if (c.compare(a[i], max) > 0) {
					max = a[i];
				}
			}
			return max;
		}
	}

	/**
	 * Returns the maximum value from the given array.
	 * @param <T> 
	 * @param a
	 * @return
	 */
	public static <T extends Comparable<? super T>> T max(T[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			T max = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i].compareTo(max) > 0) {
					max = a[i];
				}
			}
			return max;
		}
	}

	/**
	 * Returns the maximum value from the given array.
	 * @param a
	 * @return
	 */
	public static byte max(byte[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			byte max = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] > max) {
					max = a[i];
				}
			}
			return max;
		}
	}
	
	/**
	 * Returns the maximum value from the given array.
	 * @param a
	 * @return
	 */
	public static char max(char[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			char max = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] > max) {
					max = a[i];
				}
			}
			return max;
		}
	}
	
	/**
	 * Returns the maximum value from the given array.
	 * @param a
	 * @return
	 */
	public static double max(double[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			double max = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] > max) {
					max = a[i];
				}
			}
			return max;
		}
	}
	
	/**
	 * Returns the maximum value from the given array.
	 * @param a
	 * @return
	 */
	public static float max(float[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			float max = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] > max) {
					max = a[i];
				}
			}
			return max;
		}
	}
	
	/**
	 * Returns the maximum value from the given array.
	 * @param a
	 * @return
	 */
	public static int max(int[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			int max = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] > max) {
					max = a[i];
				}
			}
			return max;
		}
	}
	
	/**
	 * Returns the maximum value from the given array.
	 * @param a
	 * @return
	 */
	public static long max(long[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			long max = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] > max) {
					max = a[i];
				}
			}
			return max;
		}
	}
	
	/**
	 * Returns the maximum value from the given array.
	 * @param a
	 * @return
	 */
	public static short max(short[] a) {
		if (empty(a)) {
			throw new IllegalArgumentException("array is empty");
		} else {
			short max = a[0];
			for (int i = 1; i < a.length; i++) {
				if (a[i] > max) {
					max = a[i];
				}
			}
			return max;
		}
	}
	

	/**
	 * Tests the given objects for equality, returning true if both objects
	 * have the same identity or if <code>o1.equals(o2)</code> returns true;
	 * otherwise returns false. Note that if both o1 and o2 are null, this
	 * operation will return true, but of only one or the other is null, this
	 * operation will return false.
	 * @param o1
	 * @param o2
	 * @return
	 */
	public static boolean equal(Object o1, Object o2) {
		if (o1 == o2) {
			return true;
		} else if (o1 == null || o2 == null) {
			return false;
		} else {
			return o1.equals(o2);
		}
	}


	/**
	 * Returns the first item from the supplied list if it is not null and has
	 * a size greater than zero, otherwise returns the supplied default.
	 * @param <T>
	 * @param list
	 * @param defaultValue
	 * @return
	 */
	public static <T> T first(List<T> list, T defaultValue) {
		if (list == null) {
			return defaultValue;
		} else if (list.size() == 0) {
			return defaultValue;
		} else {
			return list.get(0);
		}
	}

	/**
	 * Returns the first choice if the first choice is not null, otherwise
	 * returns the second choice.
	 * @param <T>
	 * @param firstChoice
	 * @param secondChoice
	 * @return
	 */
	public static <T> T choose(T firstChoice, T secondChoice) {
		return firstChoice == null ? secondChoice : firstChoice;
	}


	/**
	 * Returns an empty list if the supplied list is null, otherwise returns
	 * the supplied list.
	 * @param <T>
	 * @param list
	 * @return
	 */
	public static <T> List<T> normalize(List<T> list) {
		if (list == null) {
			return Collections.emptyList();
		} else {
			return list;
		}
	}


	/**
	 * Returns true if the given string is null, has a length of zero, or
	 * contains only whitespace.
	 * @param s
	 * @return
	 */
	public static boolean blank(String s) {
		return s == null || s.trim().length() == 0;
	}


	/**
	 * Returns true if the given string is null or has a length of zero.
	 * @param s
	 * @return
	 */
	public static boolean empty(String s) {
		return s == null || s.length() == 0;
	}

	/**
	 * Returns true if the given map is null or has a size of zero.
	 * @param m
	 * @return
	 */
	public static boolean empty(Map m) {
		return m == null || m.size() == 0;
	}

	/**
	 * Returns true if the given collection is null or has a size of zero.
	 * @param c
	 * @return
	 */
	public static boolean empty(Collection c) {
		return c == null || c.size() == 0;
	}

	/**
	 * Returns true if the given array is null or has a length of zero.
	 * @param a 
	 * @return
	 */
	public static boolean empty(Object[] a) {
		return a == null || a.length == 0;
	}

	/**
	 * Returns true if the given array is null or has a length of zero.
	 * @param a 
	 * @return
	 */
	public static boolean empty(boolean[] a) {
		return a == null || a.length == 0;
	}

	/**
	 * Returns true if the given array is null or has a length of zero.
	 * @param a 
	 * @return
	 */
	public static boolean empty(byte[] a) {
		return a == null || a.length == 0;
	}

	/**
	 * Returns true if the given array is null or has a length of zero.
	 * @param a 
	 * @return
	 */
	public static boolean empty(char[] a) {
		return a == null || a.length == 0;
	}

	/**
	 * Returns true if the given array is null or has a length of zero.
	 * @param a 
	 * @return
	 */
	public static boolean empty(double[] a) {
		return a == null || a.length == 0;
	}

	/**
	 * Returns true if the given array is null or has a length of zero.
	 * @param a 
	 * @return
	 */
	public static boolean empty(float[] a) {
		return a == null || a.length == 0;
	}

	/**
	 * Returns true if the given array is null or has a length of zero.
	 * @param a 
	 * @return
	 */
	public static boolean empty(int[] a) {
		return a == null || a.length == 0;
	}

	/**
	 * Returns true if the given array is null or has a length of zero.
	 * @param a 
	 * @return
	 */
	public static boolean empty(long[] a) {
		return a == null || a.length == 0;
	}

	/**
	 * Returns true if the given array is null or has a length of zero.
	 * @param a 
	 * @return
	 */
	public static boolean empty(short[] a) {
		return a == null || a.length == 0;
	}


	/**
	 * Returns that portion of the given string that comes after the supplied
	 * prefix, or returns a zero-length string if the given string does not
	 * contain the supplied prefix.
	 * @param s
	 * @param prefix
	 * @return
	 */
	public static String substringAfter(String s, String prefix) {
		if (s.startsWith(prefix)) {
			return s.substring(prefix.length());
		} else {
			return "";
		}
	}

	/**
	 * Returns that portion of the given string that comes before the supplied
	 * suffix, or returns a zero-length string if the given string does not
	 * contain the supplied suffix.
	 * @param s
	 * @param suffix
	 * @return
	 */
	public static String substringBefore(String s, String suffix) {
		if (s.endsWith(suffix)) {
			return s.substring(0, s.length() - suffix.length());
		} else {
			return "";
		}
	}
	

	private CommonUtil() {
	}
}
